package model;

import java.util.ArrayList;

public class NoBracesTerm {

	/**
	 * if its null then there is only 1 math symbol and the calc can start
	 */
	public ArrayList<ElementarTerm> calcLog = new ArrayList<ElementarTerm>();
	public String termId;
	public String term;

	public NoBracesTerm(String termId, String term) {
		this.termId = termId;
		this.term = term;
		analyseTerm(term);
	}

	/**
	 * 1. find ^ (important (2^2)^3 != 2^(2^3) so find the last ^ first) 2. find
	 * * 3. find / 4. find + 5. find -
	 * 
	 * @param currentTerm
	 */
	private void analyseTerm(String currentTerm) {

		if (StringAnalyser.onlyOneOperator(currentTerm)) {
			int operatorPos = StringAnalyser.getOperatorPos(currentTerm);
			ElementarTerm newEleTerm = getElementarTerm(currentTerm,
					operatorPos);
			calcLog.add(newEleTerm);
		} else {
			StringPosVec lastPot = StringAnalyser.getLastPotBlock(currentTerm);
			if (lastPot != null) {
				currentTerm = atEletermToList(1, currentTerm, lastPot);
				analyseTerm(currentTerm);
				return;
			}
			StringPosVec firstMult = StringAnalyser.getFirstCalcBlock(
					currentTerm, '*');
			if (firstMult != null) {
				currentTerm = atEletermToList(2, currentTerm, firstMult);
				analyseTerm(currentTerm);
				return;
			}
			StringPosVec firstDiv = StringAnalyser.getFirstCalcBlock(
					currentTerm, '/');
			if (firstDiv != null) {
				currentTerm = atEletermToList(3, currentTerm, firstDiv);
				analyseTerm(currentTerm);
				return;
			}
			StringPosVec firstAdd = StringAnalyser.getFirstCalcBlock(
					currentTerm, '+');
			if (firstAdd != null) {
				currentTerm = atEletermToList(4, currentTerm, firstAdd);
				analyseTerm(currentTerm);
				return;
			}
			StringPosVec firstSub = StringAnalyser.getFirstCalcBlock(
					currentTerm, '-');
			if (firstSub != null) {
				currentTerm = atEletermToList(5, currentTerm, firstSub);
				analyseTerm(currentTerm);
				return;
			}
		}
	}

	/**
	 * @param typeOFTerm
	 * @param currentTerm
	 * @param operatorPosition
	 * @return the new current string with the replaces subterm
	 */
	private String atEletermToList(int typeOFTerm, String currentTerm,
			StringPosVec operatorPosition) {

		String varName = VarNameFactory.getNewVarName();
		String replacedPart = StringAnalyser.getSubTerm(currentTerm,
				operatorPosition);

		ElementarTerm newEleTerm = null;
		switch (typeOFTerm) {
		case 1:
			newEleTerm = new PotTerm(varName, replacedPart);
			break;
		case 2:
			newEleTerm = new MultTerm(varName, replacedPart);
			break;
		case 3:
			newEleTerm = new DivTerm(varName, replacedPart);
			break;
		case 4:
			newEleTerm = new AddTerm(varName, replacedPart);
			break;
		case 5:
			newEleTerm = new SubTerm(varName, replacedPart);
			break;
		default:
			break;
		}

		calcLog.add(newEleTerm);
		return StringAnalyser.replacePart(currentTerm, varName,
				operatorPosition);

	}

	private ElementarTerm getElementarTerm(String t, int operatorPos) {
		char op = t.charAt(operatorPos);
		if (op == '+')
			return new AddTerm(termId, t);
		if (op == '-')
			return new SubTerm(termId, t);
		if (op == '*')
			return new MultTerm(termId, t);
		if (op == '/')
			return new DivTerm(termId, t);
		if (op == '^')
			return new PotTerm(termId, t);
		return null;
	}

	@Override
	public String toString() {
		if (calcLog != null)
			return calcLog.toString();
		return termId + "=" + term;
	}

	/**
	 * here the new values are calculated and added to the varValueList
	 * 
	 * @param varValueList
	 * @return the updated var-value-List
	 */
	public void executeOn(VarValueList varValueList) {
		for (int i = 0; i < calcLog.size(); i++) {
			calcLog.get(i).execute(varValueList);
		}
	}

	public void speedExecuteOn(SpeedVarValueList speedVarValueList) {
		for (int i = 0; i < calcLog.size(); i++) {
			calcLog.get(i).speedExecute(speedVarValueList);
		}
	}
}
